#pragma once

#include "../metaprogramming/Metaprogramming.h"

#define HIJACK_ATTRIBUTE(ClassName, AttributeName) \
namespace HijackGenerate{ \
template<typename T, T ClassName::*Attribute> \
struct Hijack_##ClassName##_##AttributeName { \
    friend auto &hijackGet_##ClassName##_##AttributeName(ClassName &object) { \
        return object.*Attribute; \
    } \
}; \
auto &hijackGet_##ClassName##_##AttributeName(ClassName &object); \
template struct Hijack_##ClassName##_##AttributeName<decltype(ClassName::AttributeName), &ClassName::AttributeName>; \
}

#define HIJACK_PP_FOREACH_1(f, o, _1) f(o,_1)
#define HIJACK_PP_FOREACH_2(f, o, _1, _2) f(o,_1)f(o,_2)
#define HIJACK_PP_FOREACH_3(f, o, _1, _2, _3) f(o,_1)f(o,_2)f(o,_3)
#define HIJACK_PP_FOREACH_4(f, o, _1, _2, _3, _4) f(o,_1)f(o,_2)f(o,_3)f(o,_4)
#define HIJACK_PP_FOREACH_5(f, o, _1, _2, _3, _4, _5) f(o,_1)f(o,_2)f(o,_3)f(o,_4)f(o,_5)
#define HIJACK_PP_FOREACH_6(f, o, _1, _2, _3, _4, _5, _6) f(o,_1)f(o,_2)f(o,_3)f(o,_4)f(o,_5)f(o,_6)
#define HIJACK_PP_FOREACH_7(f, o, _1, _2, _3, _4, _5, _6, _7) f(o,_1)f(o,_2)f(o,_3)f(o,_4)f(o,_5)f(o,_6)f(o,_7)
#define HIJACK_PP_FOREACH_8(f, o, _1, _2, _3, _4, _5, _6, _7, _8) f(o,_1)f(o,_2)f(o,_3)f(o,_4)f(o,_5)f(o,_6)f(o,_7)f(o,_8)
#define HIJACK_PP_FOREACH_9(f, o, _1, _2, _3, _4, _5, _6, _7, _8, _9) f(o,_1)f(o,_2)f(o,_3)f(o,_4)f(o,_5)f(o,_6)f(o,_7)f(o,_8)f(o,_9)
#define HIJACK_PP_FOREACH_10(f, o, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) f(o,_1)f(o,_2)f(o,_3)f(o,_4)f(o,_5)f(o,_6)f(o,_7)f(o,_8)f(o,_9)f(o,_10)
#define HIJACK_PP_FOREACH_11(f, o, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) f(o,_1)f(o,_2)f(o,_3)f(o,_4)f(o,_5)f(o,_6)f(o,_7)f(o,_8)f(o,_9)f(o,_10)f(o,_11)
#define HIJACK_PP_FOREACH_12(f, o, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) f(o,_1)f(o,_2)f(o,_3)f(o,_4)f(o,_5)f(o,_6)f(o,_7)f(o,_8)f(o,_9)f(o,_10)f(o,_11)f(o,_12)
#define HIJACK_PP_FOREACH_13(f, o, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) f(o,_1)f(o,_2)f(o,_3)f(o,_4)f(o,_5)f(o,_6)f(o,_7)f(o,_8)f(o,_9)f(o,_10)f(o,_11)f(o,_12)f(o,_13)
#define HIJACK_PP_FOREACH_14(f, o, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14) f(o,_1)f(o,_2)f(o,_3)f(o,_4)f(o,_5)f(o,_6)f(o,_7)f(o,_8)f(o,_9)f(o,_10)f(o,_11)f(o,_12)f(o,_13)f(o,_14)
#define HIJACK_PP_FOREACH_15(f, o, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) f(o,_1)f(o,_2)f(o,_3)f(o,_4)f(o,_5)f(o,_6)f(o,_7)f(o,_8)f(o,_9)f(o,_10)f(o,_11)f(o,_12)f(o,_13)f(o,_14)f(o,_15)
#define HIJACK_PP_FOREACH_16(f, o, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) f(o,_1)f(o,_2)f(o,_3)f(o,_4)f(o,_5)f(o,_6)f(o,_7)f(o,_8)f(o,_9)f(o,_10)f(o,_11)f(o,_12)f(o,_13)f(o,_14)f(o,_15)f(o,_16)
#define HIJACK_PP_FOREACH_17(f, o, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17) f(o,_1)f(o,_2)f(o,_3)f(o,_4)f(o,_5)f(o,_6)f(o,_7)f(o,_8)f(o,_9)f(o,_10)f(o,_11)f(o,_12)f(o,_13)f(o,_14)f(o,_15)f(o,_16)f(o,_17)
#define HIJACK_PP_FOREACH_18(f, o, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18) f(o,_1)f(o,_2)f(o,_3)f(o,_4)f(o,_5)f(o,_6)f(o,_7)f(o,_8)f(o,_9)f(o,_10)f(o,_11)f(o,_12)f(o,_13)f(o,_14)f(o,_15)f(o,_16)f(o,_17)f(o,_18)
#define HIJACK_PP_FOREACH_19(f, o, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19) f(o,_1)f(o,_2)f(o,_3)f(o,_4)f(o,_5)f(o,_6)f(o,_7)f(o,_8)f(o,_9)f(o,_10)f(o,_11)f(o,_12)f(o,_13)f(o,_14)f(o,_15)f(o,_16)f(o,_17)f(o,_18)f(o,_19)
#define HIJACK_PP_FOREACH_20(f, o, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20) f(o,_1)f(o,_2)f(o,_3)f(o,_4)f(o,_5)f(o,_6)f(o,_7)f(o,_8)f(o,_9)f(o,_10)f(o,_11)f(o,_12)f(o,_13)f(o,_14)f(o,_15)f(o,_16)f(o,_17)f(o,_18)f(o,_19)f(o,_20)
#define HIJACK_PP_FOREACH(ClassName, ...) CONCAT(HIJACK_PP_FOREACH_,CALL(COUNT_ARGS(__VA_ARGS__))(HIJACK_ATTRIBUTE,ClassName,__VA_ARGS__))

/**
  * @brief  注册类私有成员劫持
  * @note   最高支持20个成员属性
  * @param  要注册的类和类的成员属性名
  */
#define HIJACK(ClassName, ...) HIJACK_PP_FOREACH(ClassName,__VA_ARGS__)